﻿using Microsoft.Extensions.DependencyInjection;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp;
using Xms.Abp.Linq;

namespace System.Linq;

public static class IQueryableExtensions
{
    private static IQueryableExecuterProvider QueryableExecuterProvider { get; set; }
    internal static ApplicationInitializationContext InitQueryableExtensions(this ApplicationInitializationContext context)
    {
        var provider = context.ServiceProvider.GetRequiredService<IQueryableExecuterProvider>();
        IQueryableExtensions.QueryableExecuterProvider = provider;
        return context;
    }
    private static IQueryableExecuterProvider GetProvider()
    {
        return QueryableExecuterProvider ?? throw new NotImplementedException("QueryableExecuterProvider is not initialize.");
    }
    public static IQueryable<T> AsNoTracking<T>(this IQueryable<T> queryable) where T : class
    {
        return GetProvider().AsNoTracking(queryable);
    }
    public static IQueryable<T> AsTracking<T>(this IQueryable<T> queryable) where T : class
    {
        return GetProvider().AsTracking(queryable);
    }
    public static IQueryable<T> Include<T, TProperty>(this IQueryable<T> queryable, Expression<Func<T, TProperty>> navigationPropertyPath) where T : class
    {
        return GetProvider().Include(queryable, navigationPropertyPath);
    }
    public static IQueryable<T> Include<T>(this IQueryable<T> queryable, string navigationPropertyPath) where T : class
    {
        return GetProvider().Include(queryable, navigationPropertyPath);
    }
    public static IQueryable<T> ThenInclude<T, TPreviousProperty, TProperty>(this IQueryable<T> queryable, Expression<Func<TPreviousProperty, TProperty>> navigationPropertyPath) where T : class
    {
        return GetProvider().ThenInclude(queryable, navigationPropertyPath);
    }
    public static IQueryable<T> IgnoreAutoIncludes<T>(this IQueryable<T> queryable) where T : class
    {
        return GetProvider().IgnoreAutoIncludes(queryable);
    }
    public static IQueryable<T> IgnoreQueryFilters<T>(this IQueryable<T> queryable) where T : class
    {
        return GetProvider().IgnoreQueryFilters(queryable);
    }
    public static IQueryable<T> TagWith<T>(this IQueryable<T> queryable, string tag) where T : class
    {
        return GetProvider().TagWith(queryable, tag);
    }
    public static IQueryable<T> TagWithCallSite<T>(this IQueryable<T> queryable, [CallerFilePath] string filePath = null, [CallerLineNumber] int lineNumber = 0) where T : class
    {
        return GetProvider().TagWithCallSite(queryable, filePath, lineNumber);
    }
    public static string ToQueryString<T>(this IQueryable<T> queryable) where T : class
    {
        return GetProvider().ToQueryString(queryable);
    }
    public static string ToString<T>(this IQueryable<T> queryable) where T : class
    {
        return GetProvider().ToString(queryable);
    }
    public static IQueryable<TResult> ProjectTo<T, TResult>(this IQueryable<T> queryable)
        where T : class
        where TResult : class, new()
    {
        return GetProvider().ProjectTo<T, TResult>(queryable);
    }




    public static Task<bool> AllAsync<T>(this IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().AllAsync(queryable, predicate, cancellationToken);
    }
    public static Task<bool> AnyAsync<T>(this IQueryable<T> queryable, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().AnyAsync(queryable, cancellationToken);
    }
    public static Task<bool> AnyAsync<T>(this IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().AnyAsync(queryable, predicate, cancellationToken);
    }
    public static Task<decimal> AverageAsync(this IQueryable<decimal> queryable, CancellationToken cancellationToken = default)
    {
        return GetProvider().AverageAsync(queryable, cancellationToken);
    }
    public static Task<float> AverageAsync<T>(this IQueryable<T> queryable, Expression<Func<T, float>> selector, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().AverageAsync(queryable, selector, cancellationToken);
    }
    public static Task<float?> AverageAsync(this IQueryable<float?> queryable, CancellationToken cancellationToken = default)
    {
        return GetProvider().AverageAsync(queryable, cancellationToken);
    }
    public static Task<float> AverageAsync(this IQueryable<float> queryable, CancellationToken cancellationToken = default)
    {
        return GetProvider().AverageAsync(queryable, cancellationToken);
    }
    public static Task<double?> AverageAsync<T>(this IQueryable<T> queryable, Expression<Func<T, double?>> selector, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().AverageAsync(queryable, selector, cancellationToken);
    }
    public static Task<double> AverageAsync<T>(this IQueryable<T> queryable, Expression<Func<T, double>> selector, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().AverageAsync(queryable, selector, cancellationToken);
    }
    public static Task<double?> AverageAsync(this IQueryable<double?> queryable, CancellationToken cancellationToken = default)
    {
        return GetProvider().AverageAsync(queryable, cancellationToken);
    }
    public static Task<double> AverageAsync(this IQueryable<double> queryable, CancellationToken cancellationToken = default)
    {
        return GetProvider().AverageAsync(queryable, cancellationToken);
    }
    public static Task<double?> AverageAsync<T>(this IQueryable<T> queryable, Expression<Func<T, long?>> selector, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().AverageAsync(queryable, selector, cancellationToken);
    }
    public static Task<double?> AverageAsync(this IQueryable<long?> queryable, CancellationToken cancellationToken = default)
    {
        return GetProvider().AverageAsync(queryable, cancellationToken);
    }
    public static Task<float?> AverageAsync<T>(this IQueryable<T> queryable, Expression<Func<T, float?>> selector, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().AverageAsync(queryable, selector, cancellationToken);
    }
    public static Task<double> AverageAsync(this IQueryable<long> queryable, CancellationToken cancellationToken = default)
    {
        return GetProvider().AverageAsync(queryable, cancellationToken);
    }
    public static Task<double?> AverageAsync<T>(this IQueryable<T> queryable, Expression<Func<T, int?>> selector, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().AverageAsync(queryable, selector, cancellationToken);
    }
    public static Task<double> AverageAsync<T>(this IQueryable<T> queryable, Expression<Func<T, int>> selector, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().AverageAsync(queryable, selector, cancellationToken);
    }
    public static Task<double?> AverageAsync(this IQueryable<int?> queryable, CancellationToken cancellationToken = default)
    {
        return GetProvider().AverageAsync(queryable, cancellationToken);
    }
    public static Task<double> AverageAsync(this IQueryable<int> queryable, CancellationToken cancellationToken = default)
    {
        return GetProvider().AverageAsync(queryable, cancellationToken);
    }
    public static Task<decimal?> AverageAsync<T>(this IQueryable<T> queryable, Expression<Func<T, decimal?>> selector, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().AverageAsync(queryable, selector, cancellationToken);
    }
    public static Task<decimal> AverageAsync<T>(this IQueryable<T> queryable, Expression<Func<T, decimal>> selector, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().AverageAsync(queryable, selector, cancellationToken);
    }
    public static Task<double> AverageAsync<T>(this IQueryable<T> queryable, Expression<Func<T, long>> selector, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().AverageAsync(queryable, selector, cancellationToken);
    }
    public static Task<decimal?> AverageAsync(this IQueryable<decimal?> queryable, CancellationToken cancellationToken = default)
    {
        return GetProvider().AverageAsync(queryable, cancellationToken);
    }
    public static Task<bool> ContainsAsync<T>(this IQueryable<T> queryable, T item, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().ContainsAsync(queryable, item, cancellationToken);
    }
    public static Task<int> CountAsync<T>(this IQueryable<T> queryable, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().CountAsync(queryable, cancellationToken);
    }
    public static Task<int> CountAsync<T>(this IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().CountAsync(queryable, predicate, cancellationToken);
    }
    public static Task<T> FirstAsync<T>(this IQueryable<T> queryable, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().FirstAsync(queryable, cancellationToken);
    }
    public static Task<T> FirstAsync<T>(this IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().FirstAsync(queryable, predicate, cancellationToken);
    }
    public static Task<T> FirstOrDefaultAsync<T>(this IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().FirstOrDefaultAsync(queryable, predicate, cancellationToken);
    }
    public static Task<T> FirstOrDefaultAsync<T>(this IQueryable<T> queryable, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().FirstOrDefaultAsync(queryable, cancellationToken);
    }
    public static Task<T> LastAsync<T>(this IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().LastAsync(queryable, predicate, cancellationToken);
    }
    public static Task<T> LastAsync<T>(this IQueryable<T> queryable, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().LastAsync(queryable, cancellationToken);
    }
    public static Task<T> LastOrDefaultAsync<T>(this IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().LastOrDefaultAsync(queryable, predicate, cancellationToken);
    }
    public static Task<T> LastOrDefaultAsync<T>(this IQueryable<T> queryable, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().LastOrDefaultAsync(queryable, cancellationToken);
    }
    public static Task<long> LongCountAsync<T>(this IQueryable<T> queryable, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().LongCountAsync(queryable, cancellationToken);
    }
    public static Task<long> LongCountAsync<T>(this IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().LongCountAsync(queryable, predicate, cancellationToken);
    }
    public static Task<TResult> MaxAsync<T, TResult>(this IQueryable<T> queryable, Expression<Func<T, TResult>> selector, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().MaxAsync(queryable, selector, cancellationToken);
    }
    public static Task<T> MaxAsync<T>(this IQueryable<T> queryable, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().MaxAsync(queryable, cancellationToken);
    }
    public static Task<T> MinAsync<T>(this IQueryable<T> queryable, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().MinAsync(queryable, cancellationToken);
    }
    public static Task<TResult> MinAsync<T, TResult>(this IQueryable<T> queryable, Expression<Func<T, TResult>> selector, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().MinAsync(queryable, selector, cancellationToken);
    }
    public static Task<T> SingleAsync<T>(this IQueryable<T> queryable, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().SingleAsync(queryable, cancellationToken);
    }
    public static Task<T> SingleAsync<T>(this IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().SingleAsync(queryable, predicate, cancellationToken);
    }
    public static Task<T> SingleOrDefaultAsync<T>(this IQueryable<T> queryable, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().SingleOrDefaultAsync(queryable, cancellationToken);
    }
    public static Task<T> SingleOrDefaultAsync<T>(this IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().SingleOrDefaultAsync(queryable, predicate, cancellationToken);
    }
    public static Task<long> SumAsync(this IQueryable<long> queryable, CancellationToken cancellationToken = default)
    {
        return GetProvider().SumAsync(queryable, cancellationToken);
    }
    public static Task<float> SumAsync<T>(this IQueryable<T> queryable, Expression<Func<T, float>> selector, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().SumAsync(queryable, selector, cancellationToken);
    }
    public static Task<decimal> SumAsync<T>(this IQueryable<T> queryable, Expression<Func<T, decimal>> selector, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().SumAsync(queryable, selector, cancellationToken);
    }
    public static Task<decimal?> SumAsync<T>(this IQueryable<T> queryable, Expression<Func<T, decimal?>> selector, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().SumAsync(queryable, selector, cancellationToken);
    }
    public static Task<int> SumAsync(this IQueryable<int> queryable, CancellationToken cancellationToken = default)
    {
        return GetProvider().SumAsync(queryable, cancellationToken);
    }
    public static Task<int?> SumAsync(this IQueryable<int?> queryable, CancellationToken cancellationToken = default)
    {
        return GetProvider().SumAsync(queryable, cancellationToken);
    }
    public static Task<int> SumAsync<T>(this IQueryable<T> queryable, Expression<Func<T, int>> selector, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().SumAsync(queryable, selector, cancellationToken);
    }
    public static Task<int?> SumAsync<T>(this IQueryable<T> queryable, Expression<Func<T, int?>> selector, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().SumAsync(queryable, selector, cancellationToken);
    }
    public static Task<float?> SumAsync<T>(this IQueryable<T> queryable, Expression<Func<T, float?>> selector, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().SumAsync(queryable, selector, cancellationToken);
    }
    public static Task<decimal?> SumAsync(this IQueryable<decimal?> queryable, CancellationToken cancellationToken = default)
    {
        return GetProvider().SumAsync(queryable, cancellationToken);
    }
    public static Task<long?> SumAsync(this IQueryable<long?> queryable, CancellationToken cancellationToken = default)
    {
        return GetProvider().SumAsync(queryable, cancellationToken);
    }
    public static Task<long?> SumAsync<T>(this IQueryable<T> queryable, Expression<Func<T, long?>> selector, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().SumAsync(queryable, selector, cancellationToken);
    }
    public static Task<double> SumAsync(this IQueryable<double> queryable, CancellationToken cancellationToken = default)
    {
        return GetProvider().SumAsync(queryable, cancellationToken);
    }
    public static Task<double?> SumAsync(this IQueryable<double?> queryable, CancellationToken cancellationToken = default)
    {
        return GetProvider().SumAsync(queryable, cancellationToken);
    }
    public static Task<double> SumAsync<T>(this IQueryable<T> queryable, Expression<Func<T, double>> selector, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().SumAsync(queryable, selector, cancellationToken);
    }
    public static Task<double?> SumAsync<T>(this IQueryable<T> queryable, Expression<Func<T, double?>> selector, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().SumAsync(queryable, selector, cancellationToken);
    }
    public static Task<float> SumAsync(this IQueryable<float> queryable, CancellationToken cancellationToken = default)
    {
        return GetProvider().SumAsync(queryable, cancellationToken);
    }
    public static Task<float?> SumAsync(this IQueryable<float?> queryable, CancellationToken cancellationToken = default)
    {
        return GetProvider().SumAsync(queryable, cancellationToken);
    }
    public static Task<long> SumAsync<T>(this IQueryable<T> queryable, Expression<Func<T, long>> selector, CancellationToken cancellationToken = default)
        where T : class
    {
        return GetProvider().SumAsync(queryable, selector, cancellationToken);
    }
    public static Task<decimal> SumAsync(this IQueryable<decimal> queryable, CancellationToken cancellationToken = default)
    {
        return GetProvider().SumAsync(queryable, cancellationToken);
    }
    public static Task<T[]> ToArrayAsync<T>(this IQueryable<T> queryable, CancellationToken cancellationToken = default)
        //where T : class
    {
        return GetProvider().ToArrayAsync(queryable, cancellationToken);
    }
    public static Task<List<T>> ToListAsync<T>(this IQueryable<T> queryable, CancellationToken cancellationToken = default)
        //where T : class
    {
        return GetProvider().ToListAsync(queryable, cancellationToken);
    }
}
